Coverage Report

Created: 2024-12-19 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\tools.proto\tools.proto\runtime\src\message\interface.rs
Line
Count
Source
1
// Copyright (c) 2024, BlockProject 3D
2
//
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification,
6
// are permitted provided that the following conditions are met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above copyright notice,
11
//       this list of conditions and the following disclaimer in the documentation
12
//       and/or other materials provided with the distribution.
13
//     * Neither the name of BlockProject 3D nor the names of its contributors
14
//       may be used to endorse or promote products derived from this software
15
//       without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
use bp3d_util::simple_error;
30
31
simple_error! {
32
    pub Error {
33
        InvalidUtf8 => "invalid UTF-8 string",
34
        Truncated => "truncated input",
35
        InvalidUnionDiscriminant(usize) => "invalid union discriminant ({})",
36
        (impl From) Io(std::io::Error) => "io error: {}"
37
    }
38
}
39
40
pub type Result<T> = std::result::Result<T, Error>;
41
42
#[derive(Default, Copy, Clone, Debug)]
43
pub struct FieldOffset {
44
    pub start: usize,
45
    pub end: usize,
46
}
47
48
impl FieldOffset {
49
6
    pub fn size(&self) -> usize {
50
6
        self.end - self.start
51
6
    }
52
}
53
54
pub struct Message<T> {
55
    data: T,
56
    size: usize,
57
}
58
59
impl<T> Message<T> {
60
365
    pub fn new(size: usize, data: T) -> Self {
61
365
        Self { data, size }
62
365
    }
63
64
357
    pub fn into_inner(self) -> T {
65
357
        self.data
66
357
    }
67
68
358
    pub fn size(&self) -> usize {
69
358
        self.size
70
358
    }
71
72
49
    pub fn map<T1, F: FnOnce(T) -> T1>(self, f: F) -> Message<T1> {
73
49
        Message::new(self.size(), f(self.into_inner()))
74
49
    }
75
}
76
77
pub trait FromBytes<'a> {
78
    type Output: Sized;
79
80
    fn from_bytes(slice: &'a [u8]) -> Result<Message<Self::Output>>;
81
    //fn copy_to_slice(&self, out_slice: &mut [u8]);
82
}
83
84
pub trait FromBytesWithOffsets<'a>: FromBytes<'a> {
85
    type Offsets: Sized;
86
87
    fn from_bytes_with_offsets(slice: &'a [u8]) -> Result<Message<(Self::Output, Self::Offsets)>>;
88
}
89
90
pub trait WriteTo {
91
    type Input<'a>: Sized;
92
93
    fn write_to<W: std::io::Write>(input: &Self::Input<'_>, out: W) -> Result<()>;
94
}
95
96
pub trait ShapeAndWrite {
97
    fn shape_and_write<W: std::io::Write>(self, out: W) -> Result<()>;
98
}
99
100
#[cfg(feature = "tokio")]
101
pub trait WriteToAsync: WriteTo {
102
    fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
103
        input: &Self::Input<'_>,
104
        out: W,
105
    ) -> impl std::future::Future<Output = Result<()>>;
106
}
107
108
pub trait WriteSelf {
109
    fn write_self<W: std::io::Write>(&self, out: W) -> Result<()>;
110
    fn size(&self) -> Result<usize>;
111
}
112
113
#[cfg(feature = "tokio")]
114
pub trait WriteSelfAsync {
115
    fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(
116
        &self,
117
        out: W,
118
    ) -> impl std::future::Future<Output = Result<()>>;
119
}
120
121
pub trait FromBytesWithHeader<'a, H> {
122
    type Output: Sized;
123
124
    fn from_bytes_with_header(slice: &'a [u8], header: &H) -> Result<Message<Self::Output>>;
125
}
126
127
pub trait WriteToWithHeader<H> {
128
    type Input<'a>: Sized;
129
130
    fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, header: &H, out: W) -> Result<()>;
131
}
132
133
pub trait ShapeHeader<H> {
134
    fn shape_header(&self, header: &mut H) -> Result<()>;
135
}
136
137
impl<H, T: WriteSelf> ShapeHeader<H> for T {
138
0
    fn shape_header(&self, _: &mut H) -> Result<()> {
139
0
        Ok(())
140
0
    }
141
}
142
143
#[cfg(feature = "tokio")]
144
pub trait WriteToWithHeaderAsync<H>: WriteToWithHeader<H> {
145
    fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(
146
        input: &Self::Input<'_>,
147
        header: &H,
148
        out: W,
149
    ) -> impl std::future::Future<Output = Result<()>>;
150
}
151
152
153
impl<'a, T: WriteTo<Input<'a> = T>> WriteSelf for T {
154
6
    fn write_self<W: std::io::Write>(&self, out: W) -> Result<()> {
155
6
        T::write_to(self, out)
156
6
    }
157
158
2
    fn size(&self) -> Result<usize> {
159
2
        crate::message::util::size_of(self)
160
2
    }
161
}
162
163
#[cfg(feature = "tokio")]
164
impl<T> WriteSelfAsync for T
165
where
166
    for<'a> T: WriteToAsync<Input<'a> = T>,
167
{
168
2
    async fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(&self, out: W) -> Result<()> {
169
2
        T::write_to_async(self, out).await
170
2
    }
171
}
172
173
impl<H, T: WriteSelf> WriteToWithHeader<H> for T {
174
    type Input<'b> = T;
175
176
2
    fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, _: &H, out: W) -> Result<()> {
177
2
        input.write_self(out)
178
2
    }
179
}
180
181
#[cfg(feature = "tokio")]
182
impl<H, T: WriteSelf + WriteSelfAsync> WriteToWithHeaderAsync<H> for T {
183
2
    fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(input: &Self::Input<'_>, _: &H, out: W) -> impl std::future::Future<Output=Result<()>> {
184
2
        input.write_self_async(out)
185
2
    }
186
}
187
188
impl<'a, H, T: FromBytes<'a>> FromBytesWithHeader<'a, H> for T {
189
    type Output = T::Output;
190
191
0
    fn from_bytes_with_header(slice: &'a [u8], _: &H) -> Result<Message<Self::Output>> {
192
0
        T::from_bytes(slice)
193
0
    }
194
}